using System;
using System.Reflection;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using Antu.Core.Services;

namespace Antu.Core.Ajax
{
    /// <summary>
    /// Provides methods to serialize and deserialize an object that implements IDictionary.
    /// </summary>
    public class HashtableConverter : AbstractJavascriptConverter
    {
        SerializerService _SerializerService = (SerializerService)ServiceManager.Manager.GetService(typeof(SerializerService));
        /// <summary>
        /// Initializes a new instance of the <see cref="HashtableConverter"/> class.
        /// </summary>
        public HashtableConverter()
            : base()
        {
            serializabletypeslist = new Type[] { typeof( Hashtable ) };
            deserializabletypeslist = new Type[] { typeof( Hashtable ) };
        }

        /// <summary>
        /// Converts an IJSONObject into an NET object.
        /// </summary>
        /// <param name="o">The IJSONObject object to convert.</param>
        /// <param name="t"></param>
        /// <returns>Returns a .NET object.</returns>
        public override object Deserialize( IJavascriptObject o , Type t )
        {

            if ( !( o is JavascriptArray ) )
                throw new NotSupportedException();

            JavascriptArray a = ( JavascriptArray )o;

            for ( int i = 0 ; i < a.Count ; i++ )
                if ( !( a[i] is JavascriptArray ) )
                    throw new NotSupportedException();

            IDictionary d = ( IDictionary )Activator.CreateInstance( t );

            object key;
            object value;
            JavascriptArray aa;

            for ( int i = 0 ; i < a.Count ; i++ )
            {
                aa = ( JavascriptArray )a[i];
                key = _SerializerService.Deserialize( ( IJavascriptObject )aa[0] , Type.GetType( ( ( JavaScriptString )aa[2] ).ToString() ) );
                value = _SerializerService.Deserialize( ( IJavascriptObject )aa[1] , Type.GetType( ( ( JavaScriptString )aa[3] ).ToString() ) );

                d.Add( key , value );
            }

            return d;

            //if ( !( o is JavascriptObject ) )
            //    throw new NotSupportedException();

            //JavascriptObject oa = ( JavascriptObject )o;
            //IDictionary od = ( IDictionary )Activator.CreateInstance( t );

            //foreach ( string k in oa.Keys )
            //{
            //    od.Add( k , _SerializerService.Deserialize( oa[k] , typeof( string ) ) );
            //}

            //return od;
        }

        /// <summary>
        /// Converts a .NET object into a JSON string.
        /// </summary>
        /// <param name="o">The object to convert.</param>
        /// <returns>Returns a JSON string.</returns>
        public override string Serialize( object o )
        {
            StringBuilder sb = new StringBuilder();
            Serialize( o , sb );
            return sb.ToString();
        }

        /// <summary>
        /// Serializes the specified o.
        /// </summary>
        /// <param name="o">The o.</param>
        /// <param name="sb">The sb.</param>
        public override void Serialize( object o , StringBuilder sb )
        {
            IDictionary dic = o as IDictionary;

            if ( dic == null )
                throw new NotSupportedException();

            IDictionaryEnumerator enumerable = dic.GetEnumerator();

            enumerable.Reset();
            bool b = true;

            sb.Append( "[" );

            while ( enumerable.MoveNext() )
            {
                if ( b )
                {
                    b = false;
                }
                else
                {
                    sb.Append( "," );
                }


                if ( enumerable.Key is String )
                    _SerializerService.Serialize(enumerable.Key, sb);
                else if ( enumerable.Key is Boolean )
                    _SerializerService.Serialize((bool)enumerable.Key == true ? "true" : "false", sb);
                else
                    JavaScriptUtil.QuoteString( enumerable.Key.ToString() , sb );

                sb.Append( ':' );
                _SerializerService.Serialize(enumerable.Value, sb);
            }

            sb.Append( "]" );
        }
    }
}